]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
ui: Implement "window doesn't respond" dialog on gnome-shell
authorCarlos Garnacho <carlosg@gnome.org>
Thu, 19 Jan 2017 18:52:18 +0000 (19:52 +0100)
committerCarlos Garnacho <carlosg@gnome.org>
Sun, 16 Jul 2017 17:28:57 +0000 (19:28 +0200)
This does allow us to use ClutterActors instead of lousy legacy tools
meant for shell scripting.

https://bugzilla.gnome.org/show_bug.cgi?id=762083

js/js-resources.gresource.xml
js/ui/closeDialog.js [new file with mode: 0644]
js/ui/windowManager.js
po/POTFILES.in
src/gnome-shell-plugin.c
src/shell-wm-private.h
src/shell-wm.c

index 71e713d2b37287ecf453e0c6a2921d9a0cd58fb0..67295a4cdb747a0c2665a9d3f1715ad3c6e8c9e7 100644 (file)
@@ -44,6 +44,7 @@
     <file>ui/boxpointer.js</file>
     <file>ui/calendar.js</file>
     <file>ui/checkBox.js</file>
+    <file>ui/closeDialog.js</file>
     <file>ui/ctrlAltTab.js</file>
     <file>ui/dash.js</file>
     <file>ui/dateMenu.js</file>
diff --git a/js/ui/closeDialog.js b/js/ui/closeDialog.js
new file mode 100644 (file)
index 0000000..9428521
--- /dev/null
@@ -0,0 +1,138 @@
+// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
+
+const Clutter = imports.gi.Clutter;
+const Gio = imports.gi.Gio;
+const GObject = imports.gi.GObject;
+const Lang = imports.lang;
+const Meta = imports.gi.Meta;
+const Shell = imports.gi.Shell;
+
+const Dialog = imports.ui.dialog;
+const Main = imports.ui.main;
+const Tweener = imports.ui.tweener;
+
+const FROZEN_WINDOW_BRIGHTNESS = -0.3
+const DIALOG_TRANSITION_TIME = 0.15
+
+const CloseDialog = new Lang.Class({
+    Name: 'CloseDialog',
+    Extends: GObject.Object,
+    Implements: [ Meta.CloseDialog ],
+    Properties: {
+        'window': GObject.ParamSpec.override('window', Meta.CloseDialog)
+    },
+
+    _init: function (window) {
+        this.parent();
+        this._window = window;
+        this._dialog = null;
+    },
+
+    get window() {
+        return this._window;
+    },
+
+    set window(window) {
+        this._window = window;
+    },
+
+    _createDialogContent: function () {
+        let tracker = Shell.WindowTracker.get_default();
+        let windowApp = tracker.get_window_app(this._window);
+
+        /* Translators: %s is an application name */
+        let title = _("ā€œ%sā€ is not responding.").format(windowApp.get_name());
+        let subtitle = _("You may choose to wait a short while for it to " +
+                         "continue or force the application to quit entirely.");
+        let icon = new Gio.ThemedIcon({ name: 'dialog-warning-symbolic' });
+        return new Dialog.MessageDialogContent({ icon, title, subtitle });
+    },
+
+    _initDialog: function () {
+        if (this._dialog)
+            return;
+
+        let windowActor = this._window.get_compositor_private();
+        this._dialog = new Dialog.Dialog(windowActor, 'close-dialog');
+        this._dialog.width = windowActor.width;
+        this._dialog.height = windowActor.height;
+
+        this._dialog.addContent(this._createDialogContent());
+        this._dialog.addButton({ label:   _('Force Quit'),
+                                 action:  Lang.bind(this, this._onClose),
+                                 default: true });
+        this._dialog.addButton({ label:  _('Wait'),
+                                 action: Lang.bind(this, this._onWait),
+                                 key:    Clutter.Escape });
+
+        global.focus_manager.add_group(this._dialog);
+    },
+
+    _addWindowEffect: function () {
+        // We set the effect on the surface actor, so the dialog itself
+        // (which is a child of the MetaWindowActor) does not get the
+        // effect applied itself.
+        let windowActor = this._window.get_compositor_private();
+        let surfaceActor = windowActor.get_first_child();
+        let effect = new Clutter.BrightnessContrastEffect();
+        effect.set_brightness(FROZEN_WINDOW_BRIGHTNESS);
+        surfaceActor.add_effect_with_name("gnome-shell-frozen-window", effect);
+    },
+
+    _removeWindowEffect: function () {
+        let windowActor = this._window.get_compositor_private();
+        let surfaceActor = windowActor.get_first_child();
+        surfaceActor.remove_effect_by_name("gnome-shell-frozen-window");
+    },
+
+    _onWait: function () {
+        this.response(Meta.CloseDialogResponse.WAIT);
+    },
+
+    _onClose: function () {
+        this.response(Meta.CloseDialogResponse.FORCE_CLOSE);
+    },
+
+    vfunc_show: function () {
+        if (this._dialog != null)
+            return;
+
+        this._addWindowEffect();
+        this._initDialog();
+
+        this._dialog.scale_y = 0;
+        this._dialog.set_pivot_point(0.5, 0.5);
+
+        Tweener.addTween(this._dialog,
+                         { scale_y: 1,
+                           transition: 'linear',
+                           time: DIALOG_TRANSITION_TIME,
+                           onComplete: Lang.bind(this, function () {
+                               Main.layoutManager.trackChrome(this._dialog, { affectsInputRegion: true });
+                           })
+                         });
+    },
+
+    vfunc_hide: function () {
+        if (this._dialog == null)
+            return;
+
+        let dialog = this._dialog;
+        this._dialog = null;
+        this._removeWindowEffect();
+
+        Tweener.addTween(dialog,
+                         { scale_y: 0,
+                           transition: 'linear',
+                           time: DIALOG_TRANSITION_TIME,
+                           onComplete: Lang.bind(this, function () {
+                               dialog.destroy();
+                           })
+                         });
+    },
+
+    vfunc_focus: function () {
+        if (this._dialog)
+            this._dialog.grab_key_focus();
+    }
+});
index 4598120947e78fe8de6b66aa44ca36611453e9d1..0b8ba53e8eaa213c941a3f056bd995b4eae867dc 100644 (file)
@@ -20,6 +20,7 @@ const Tweener = imports.ui.tweener;
 const WindowMenu = imports.ui.windowMenu;
 const PadOsd = imports.ui.padOsd;
 const EdgeDragAction = imports.ui.edgeDragAction;
+const CloseDialog = imports.ui.closeDialog;
 
 const SHELL_KEYBINDINGS_SCHEMA = 'org.gnome.shell.keybindings';
 const MINIMIZE_WINDOW_ANIMATION_TIME = 0.2;
@@ -710,6 +711,7 @@ const WindowManager = new Lang.Class({
         this._shellwm.connect('destroy', Lang.bind(this, this._destroyWindow));
         this._shellwm.connect('filter-keybinding', Lang.bind(this, this._filterKeybinding));
         this._shellwm.connect('confirm-display-change', Lang.bind(this, this._confirmDisplayChange));
+        this._shellwm.connect('create-close-dialog', Lang.bind(this, this._createCloseDialog));
         global.screen.connect('restacked', Lang.bind(this, this._syncStacking));
 
         this._workspaceSwitcherPopup = null;
@@ -1971,6 +1973,10 @@ const WindowManager = new Lang.Class({
         dialog.open();
     },
 
+    _createCloseDialog: function (shellwm, window) {
+        return new CloseDialog.CloseDialog(window);
+    },
+
     _showResizePopup: function(display, show, rect, displayW, displayH) {
         if (show) {
             if (!this._resizePopup)
index 121c5129f6260f70a2a2fa70146d08699efd94ac..bc9e6ac5546d7fb979bb319ec5450b5b26504d5a 100644 (file)
@@ -17,6 +17,7 @@ js/ui/appFavorites.js
 js/ui/audioDeviceSelection.js
 js/ui/backgroundMenu.js
 js/ui/calendar.js
+js/ui/closeDialog.js
 js/ui/components/automountManager.js
 js/ui/components/autorunManager.js
 js/ui/components/keyring.js
index c9a8917e2073794994a4d60f6d61c87c340e759c..c047d0dde399b32f170822028dc56673ba4b32e9 100644 (file)
@@ -88,6 +88,8 @@ static void gnome_shell_plugin_confirm_display_change (MetaPlugin *plugin);
 
 static const MetaPluginInfo *gnome_shell_plugin_plugin_info   (MetaPlugin *plugin);
 
+static MetaCloseDialog * gnome_shell_plugin_create_close_dialog (MetaPlugin *plugin,
+                                                              MetaWindow *window);
 
 #define GNOME_TYPE_SHELL_PLUGIN            (gnome_shell_plugin_get_type ())
 #define GNOME_SHELL_PLUGIN(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GNOME_TYPE_SHELL_PLUGIN, GnomeShellPlugin))
@@ -149,6 +151,8 @@ gnome_shell_plugin_class_init (GnomeShellPluginClass *klass)
   plugin_class->confirm_display_change = gnome_shell_plugin_confirm_display_change;
 
   plugin_class->plugin_info       = gnome_shell_plugin_plugin_info;
+
+  plugin_class->create_close_dialog = gnome_shell_plugin_create_close_dialog;
 }
 
 static void
@@ -425,3 +429,10 @@ MetaPluginInfo *gnome_shell_plugin_plugin_info (MetaPlugin *plugin)
 
   return &info;
 }
+
+static MetaCloseDialog *
+gnome_shell_plugin_create_close_dialog (MetaPlugin *plugin,
+                                        MetaWindow *window)
+{
+  return _shell_wm_create_close_dialog (get_shell_wm (), window);
+}
index 7e0399c5918d40496f6e034d4472fdc4bc2a855f..46faae9d7f41be7ff0f7cbce9e03381febbd7a44 100644 (file)
@@ -52,6 +52,9 @@ gboolean _shell_wm_filter_keybinding (ShellWM             *wm,
 
 void _shell_wm_confirm_display_change (ShellWM            *wm);
 
+MetaCloseDialog * _shell_wm_create_close_dialog (ShellWM     *wm,
+                                                 MetaWindow  *window);
+
 G_END_DECLS
 
 #endif /* __SHELL_WM_PRIVATE_H__ */
index 0b3f9258c2588c01a58453bc32c8f06a646f929a..41ad08a0900deeffd87b558dcd2ce7b90f3f5eff 100644 (file)
@@ -33,6 +33,7 @@ enum
   SHOW_WINDOW_MENU,
   FILTER_KEYBINDING,
   CONFIRM_DISPLAY_CHANGE,
+  CREATE_CLOSE_DIALOG,
 
   LAST_SIGNAL
 };
@@ -168,6 +169,22 @@ shell_wm_class_init (ShellWMClass *klass)
                   0,
                   NULL, NULL, NULL,
                   G_TYPE_NONE, 0);
+  /**
+   * ShellWM::create-close-dialog:
+   * @wm: The WM
+   * @window: The window to create the dialog for
+   *
+   * Creates a close dialog for the given window.
+   *
+   * Returns: (transfer full): The close dialog instance.
+   */
+  shell_wm_signals[CREATE_CLOSE_DIALOG] =
+    g_signal_new ("create-close-dialog",
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_LAST,
+                  0,
+                  NULL, NULL, NULL,
+                  META_TYPE_CLOSE_DIALOG, 1, META_TYPE_WINDOW);
 }
 
 void
@@ -386,6 +403,17 @@ _shell_wm_confirm_display_change (ShellWM *wm)
   g_signal_emit (wm, shell_wm_signals[CONFIRM_DISPLAY_CHANGE], 0);
 }
 
+MetaCloseDialog *
+_shell_wm_create_close_dialog (ShellWM    *wm,
+                               MetaWindow *window)
+{
+  MetaCloseDialog *dialog;
+
+  g_signal_emit (wm, shell_wm_signals[CREATE_CLOSE_DIALOG], 0, window, &dialog);
+
+  return dialog;
+}
+
 /**
  * shell_wm_new:
  * @plugin: the #MetaPlugin